/*******************************************************************************
    Project: JobShop Problem using Genetic Algorithm: Serial Approach
    File: UniverseGenerator.cpp
    Author: ChinniKrishna Kothapalli
    Email: kothapal@pdx.edu
    Revision: 0.1
    Date & Time: 11/08/2013

    Description:
    Generates universe with required number of individuals.
    Required number of individuals are mentioned with population parameter
*******************************************************************************/

/*
** ----------------------------------------------------------------------------
** S Y S T E M   I N C L U D E S
** ----------------------------------------------------------------------------
*/
#include <iostream>
#include <ctime>
#include <cstdlib>

/*
** ----------------------------------------------------------------------------
** C O M P O N E N T   I N C L U D E S
** ----------------------------------------------------------------------------
*/
#include "types.h"
#include "UniverseGenerator.h"
#include "EvaluateIndividual.h"


extern unsigned int rand_seeds[];
//Gene Codebase
static const char alphanum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";


//Function to Generate Random Character
static char GetRandomChar(int Position)
{
    return alphanum[rand_r(&rand_seeds[RS_GET_RAND_CHAR]) % Position];
}

//Print Individual
int PrintIndividual(const Individual& Ind)
{
        cout << "Chromosome "<< Ind.Chromosome;
        cout << "\tFitness " << Ind.Fitness <<endl;
    return 0;
}


/*============================================================================
**
** Function Name:       CreateUniverse
**
** Description:         Creates the population (universe) of individuals
**
** Invocation:          main
**
** Input Parameters:    int Population : The number of individuals to generate
** 						Individual* Universe : Universe buffer
** 						unsigned int NumJobs : Number of Jobs
** 						unsigned int NumMachines : Number of Machines
**
** Return Values:       int (0 if problems, 1 otherwise)
**
**==========================================================================*/

int CreateUniverse(int Population, Individual* Universe, unsigned int NumJobs, unsigned int NumMachines)
{
    if(!Universe)
        return 0;

    for(int i = 0; i < Population; i++)
    {
        Universe[i].Chromosome = GenerateChromosome(NumJobs,NumMachines);
        Universe[i].Fitness = 0.0;
    }
    return 1;
}



/*============================================================================
**
** Function Name:       GenerateChromosome
**
** Description:         Generates a random individual by permutations with
** 						repetitions
**
** Invocation:          CreateUniverse
**
** Input Parameters:    unsigned int NumJobs : Number of Jobs
** 						unsigned int NumMachines : Number of Machines
**
** Return Values:       string : The generated chromosome
**
**==========================================================================*/

string GenerateChromosome(int Jobs,int Machines)
{
    //Variables
	//Length of Chromosome
	int ChromosomeLength = Jobs * Machines;

	//Position for alphanum
	int Position = Jobs;

	//Counter to enforce numbering
	int* Counter = new int[Jobs];

	//Storage for the char returned by GetRandomChar
	char Test;

	//Actual Chromosome generated
	string Chromosome;

	//General purpose counter
	int i;

    //Initialize the Counter Array
    for(int cnt = 0; cnt < Jobs; cnt++)
        Counter[cnt]=0;

    //Filling the Chromosome with correct number of genes
    for(i = 0; i < ChromosomeLength;)
    {
        //Get the Character
        Test = GetRandomChar(Position);

        //Test to know if chromosome is filled with equal number of genes
        for(int j = 0; j < Position; j++)
        {
            if(Test == alphanum[j])
            {
                if(Counter[j] < Machines)
                {
                    Counter[j]++;
                    Chromosome.append(string(1,Test));
                    i++;
                    break;
                }
                else
                    break;
            }
        }
    }
    //Null terminate the string
    Chromosome[ChromosomeLength] = '\0';


    if (Counter)
    	delete[] Counter;

    return Chromosome;
}
